package com.hait.mypicture.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hait.mypicture.exception.BusinessException;
import com.hait.mypicture.exception.ErrorCode;
import com.hait.mypicture.exception.ThrowUtils;
import com.hait.mypicture.mapper.SpaceMapper;
import com.hait.mypicture.model.dto.space.analyze.*;
import com.hait.mypicture.model.entity.Picture;
import com.hait.mypicture.model.entity.Space;
import com.hait.mypicture.model.entity.User;
import com.hait.mypicture.model.vo.space.analyze.*;
import com.hait.mypicture.service.PictureService;
import com.hait.mypicture.service.SpaceAnalyzeService;
import com.hait.mypicture.service.SpaceService;
import com.hait.mypicture.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author DELL
 * @description 针对表【space(空间)】的数据库操作Service实现
 * @createDate 2025-08-15 19:51:35
 */
@Service
public class SpaceAnalyzeServiceImpl extends ServiceImpl<SpaceMapper, Space>
        implements SpaceAnalyzeService {

    @Resource
    private UserService userService;

    @Resource
    private SpaceService spaceService;

    @Resource
    private PictureService pictureService;


    /**
     * 空间使用情况分析
     *
     * @param spaceAnalyzeRequest 空间分析请求
     * @param loginUser           登录用户
     * @return 空间使用情况分析结果
     */
    @Override
    public SpaceUsageAnalyzeResponse analyzeSpaceUsage(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        // 全空间或公共图库，需要从picture表中查询
        if (spaceAnalyzeRequest.isQueryPublic() || spaceAnalyzeRequest.isQueryAll()) {
            // 权限校验，仅管理员可以使用
            checkSpaceAnalyzeAuth(spaceAnalyzeRequest, loginUser);
            // 查询条件封装
            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("picSize");
            //补充查询参数
            fillAnalyzeQueryWrapper(spaceAnalyzeRequest, queryWrapper);
            List<Object> picObjectList = pictureService.getBaseMapper().selectObjs(queryWrapper);
            long usedSize = picObjectList.stream().mapToLong(obj -> (Long) obj).sum();
            long usedCount = picObjectList.size();

            // 封装返回结果
            SpaceUsageAnalyzeResponse analyzeResponse = new SpaceUsageAnalyzeResponse();
            analyzeResponse.setUsedSize(usedSize);
            analyzeResponse.setUsedCount(usedCount);
            // 公共图库（全部空间）无最大容量和个数限制
            analyzeResponse.setMaxSize(null);
            analyzeResponse.setSizeUsageRatio(null);
            analyzeResponse.setMaxCount(null);
            analyzeResponse.setCountUsageRatio(null);
            return analyzeResponse;
        } else {
            // 特定空间分析，需要从space表中查询
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR);
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(ObjUtil.isEmpty(space), ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            // 校验权限
            checkSpaceAnalyzeAuth(spaceAnalyzeRequest, loginUser);
            // 封装返回结果
            SpaceUsageAnalyzeResponse analyzeResponse = new SpaceUsageAnalyzeResponse();
            analyzeResponse.setUsedSize(space.getTotalSize());
            analyzeResponse.setUsedCount(space.getTotalCount());
            // 特定空间具有最大容量和最大个数限制
            analyzeResponse.setMaxSize(space.getMaxSize());
            analyzeResponse.setMaxCount(space.getMaxCount());
            double sizeUsageRatio = NumberUtil.round(space.getTotalSize() * 100.0 / space.getMaxSize(), 2).doubleValue();
            analyzeResponse.setSizeUsageRatio(sizeUsageRatio);
            double countUsageRatio = NumberUtil.round(space.getTotalCount() * 100.0 / space.getMaxCount(), 2).doubleValue();
            analyzeResponse.setCountUsageRatio(countUsageRatio);
            return analyzeResponse;
        }
    }

    /**
     * 空间图片分类分析
     *
     * @param spaceCategoryAnalyzeRequest 空间图片分类分析请求
     * @param loginUser                   登录用户
     * @return 空间图片分类分析结果
     */
    @Override
    public List<SpaceCategoryAnalyzeResponse> analyzeSpaceCategory(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceCategoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        // 权限校验
        checkSpaceAnalyzeAuth(spaceCategoryAnalyzeRequest, loginUser);

        // 查询条件封装
        QueryWrapper<Picture> wrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest, wrapper);

        // 使用myabtis-plus 分组查询
        wrapper.select("category", "count(id) as count", "sum(picSize) as totalSize")
                .groupBy("category");

        // 查询并封装返回结果
        return pictureService.getBaseMapper().selectMaps(wrapper)
                .stream()
                .map(result -> {
                    String category = (String) result.get("category");
                    Long count = (Long) result.get("count");
                    Long totalSize = (Long) result.get("totalSize");
                    return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
                }).collect(Collectors.toList());
    }

    /**
     * 空间图片标签分析
     *
     * @param spaceTagAnalyzeRequest 空间标签分析请求
     * @param loginUser              登录用户
     * @return 空间标签分析结果
     */
    @Override
    public List<SpaceTagAnalyzeResponse> analyzeSpaceTag(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceTagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        // 权限校验
        checkSpaceAnalyzeAuth(spaceTagAnalyzeRequest, loginUser);

        // 查询条件封装
        QueryWrapper<Picture> wrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest, wrapper);

        // 使用myabtis-plus 分组查询
        wrapper.select("tags");

        List<String> tagsJsonList = pictureService.getBaseMapper()
                .selectObjs(wrapper).stream()
                .filter(ObjUtil::isNotEmpty)
                .map(Object::toString)
                .collect(Collectors.toList());

        // 解析标签并统计次数
        Map<String, Long> tagCountMap = tagsJsonList.stream()
                .flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        // 封装返回结果,并将结果按照次数进行排序
        return tagCountMap.entrySet().stream()
                .sorted((entry1, entry2) -> Long.compare(entry2.getValue(), entry1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 空间图片大小分析
     *
     * @param spaceSizeAnalyzeRequest 空间大小分析请求
     * @param loginUser               登录用户
     * @return 空间图片大小分析结果
     */
    @Override
    public List<SpaceSizeAnalyzeResponse> analyzeSpaceSize(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceSizeAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 权限校验
        checkSpaceAnalyzeAuth(spaceSizeAnalyzeRequest, loginUser);

        // 查询条件封装
        QueryWrapper<Picture> wrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceSizeAnalyzeRequest, wrapper);

        wrapper.select("picSize");
        List<Long> picSizeList = pictureService.getBaseMapper().selectObjs(wrapper)
                .stream()
                .filter(ObjUtil::isNotEmpty)
                .map(size -> (Long) size)
                .collect(Collectors.toList());

        // 定义分段范围，注意使用有序Map
        LinkedHashMap<String, Long> sizeRanges = new LinkedHashMap<>();
        sizeRanges.put("<100KB", picSizeList.stream().filter(size -> size < 100 * 1024).count());
        sizeRanges.put("100KB-500KB", picSizeList.stream().filter(size -> size >= 100 * 1024 && size < 500 * 1024).count());
        sizeRanges.put("500KB-1MB", picSizeList.stream().filter(size -> size >= 500 * 1024 && size < 1 * 1024 * 1024).count());
        sizeRanges.put(">1MB", picSizeList.stream().filter(size -> size >= 1 * 1024 * 1024).count());

        return sizeRanges.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 获取空间用户分析
     *
     * @param spaceUserAnalyzeRequest 空间用户分析请求
     * @param loginUser               登录用户
     * @return 空间用户分析结果
     */
    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest,
                                                              User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 权限校验
        checkSpaceAnalyzeAuth(spaceUserAnalyzeRequest, loginUser);

        // 查询条件封装
        QueryWrapper<Picture> wrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest, wrapper);

        Long userId = loginUser.getId();
        wrapper.eq(ObjUtil.isEmpty(userId), "userId", userId);
        // 补充分析维度，每日、每周、每月。
        String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
        switch (timeDimension) {
            case "day":
                wrapper.select("DATE_FORMAT(createTime,'%Y-%m-%d') as period", "count(*) as count");
                break;
            case "week":
                wrapper.select("YEARWEEK(createTime) as period", "count(*) as count");
                break;
            case "month":
                wrapper.select("DATE_FORMAT(createTime,'%Y-%m') as period", "count(*) as count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "时间维度错误");
        }
        wrapper.groupBy("period").orderByAsc("period");

        List<Map<String, Object>> queryResult = pictureService.getBaseMapper().selectMaps(wrapper);

        return queryResult.stream().map(result -> {
            String period = (String) result.get("period");
            Long count = (Long) result.get("count");
            return new SpaceUserAnalyzeResponse(period, count);
        }).collect(Collectors.toList());
    }

    /**
     * 获取空间使用排行
     *
     * @param spaceRankAnalyzeRequest 空间使用排行分析请求
     * @param loginUser               登录用户
     * @return 空间使用排行
     */
    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 权限校验，仅管理员使用
        ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        // 查询条件封装
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id","spaceName","userId","totalSize")
                .orderByDesc("totalSize")
                .last("limit " + spaceRankAnalyzeRequest.getTopN()); //取前 N 名

        return spaceService.list(queryWrapper);
    }

    /**
     * 空间分析权限校验
     *
     * @param spaceAnalyzeRequest 空间分析请求对象
     * @param loginUser           登录用户
     */
    private void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
        if (queryPublic || queryAll) {
            // 全空间分析或者公共图库分析，仅管理员可使用
            ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        } else {
            //表示分析特定空间，则需要空间创建者身份和管理员身份
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(ObjUtil.isEmpty(spaceId), ErrorCode.PARAMS_ERROR);
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(ObjUtil.isEmpty(space), ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            // 校验权限，仅空间创建者和管理员可用
            spaceService.checkSpaceAuth(loginUser, space);
        }
    }

    /**
     * 根据请求对象，封装查询条件
     *
     * @param spaceAnalyzeRequest 空间分析请求对象
     * @param queryWrapper        查询条件封装对象
     */
    private void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
        if (queryAll) {
            // 全空间分析
            return;
        }
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        if (queryPublic) {
            // 公共图库分析
            queryWrapper.isNull("spaceId");
            return;
        }
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        if (spaceId != null) {
            // 特定空间分析
            queryWrapper.eq("spaceId", spaceId);
            return;
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询范围");
    }
}




